package com.zhuangjie.event.service;

import com.zhaungjie.base.utils.json.JsonUtils;
import com.zhaungjie.base.utils.StringUtils;
import com.zhuangjie.event.annotation.ModuleEventName;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.Topic;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;

/**
 * 抽象模块事件服务
 * redis key  ->  moduleName::eventName
 *
 * @author zhuangjie
 * @date 2023/12/07
 */
@Configuration
@Slf4j
public abstract class AbstractModuleEventService implements ModuleEventService {
    @Autowired
    protected RedisTemplate redisTemplate;

    private String eventName;


    /**
     * 产生事件名称 set value for eventName
     * @param environment
     */
    @Autowired
    private void setEventName(Environment environment) {
        String prefix = "";
        ModuleEventName[] annotationsByType = this.getClass().getAnnotationsByType(ModuleEventName.class);

        if (annotationsByType != null && annotationsByType.length > 0) {
            if (annotationsByType.length > 1) {
                throw new RuntimeException("ModuleEvent框架：不能同时标注多个ModuleEventName注解");
            }
            ModuleEventName moduleEventName = annotationsByType[0];
            prefix = moduleEventName.moduleNamePrefix() ? environment.getProperty("spring.application.name") + "::" : prefix;
        }

        String event = (annotationsByType == null || annotationsByType.length == 0 || StringUtils.isBlank(annotationsByType[0].value()))
                ? this.getClass().getSimpleName()
                : annotationsByType[0].value();

        this.eventName = prefix + event;
    }


    /**
     * 被AutoRegister::register调用收集注册信息
     */
    public void register(Map<MessageListener, Collection<? extends Topic>> mp) {
        log.info("ModuleEvent框架:正在添加redis-pub/sub监听：" + eventName);
        mp.put(this::on, Collections.singletonList(new PatternTopic(eventName)));
    }


    /**
     * 子类要pub时调用
     * @param eventData
     */
    @Override
    public void emit(Object eventData) {
        redisTemplate.convertAndSend(eventName, JsonUtils.stringify(eventData));
    }

}
